package mk.jug.academy.service;

import java.util.List;
import java.util.logging.Logger;

import javax.persistence.NoResultException;

import mk.jug.academy.dao.CourseDAO;
import mk.jug.academy.dao.LecturerDAO;
import mk.jug.academy.exception.BusinessException;
import mk.jug.academy.model.Course;
import mk.jug.academy.model.Lecturer;
import mk.jug.academy.model.Page;
import mk.jug.academy.model.status.LecturerStatus;
import mk.jug.academy.preconditions.ErrorCodes;
import mk.jug.academy.preconditions.LecturerPreconditions;
import mk.jug.academy.preconditions.PreconditionExceptions;
import mk.jug.academy.util.Utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;


/**
 * Provides the business logic implementation for the {@link LecturerService}.
 *
 * @author Ice.Penov
 */
@Service
public class LecturerServiceImpl implements LecturerService {

	@Autowired private LecturerDAO lecturerDAO;
	@Autowired private CourseDAO courseDAO;
	
	private static Logger LOG = Logger.getLogger(LecturerServiceImpl.class.getName());
	
	@Override
	public void registerLecturer(Lecturer lecturer) {
		LecturerPreconditions.registerLecturer(lecturer);
		lecturer.setStatus(LecturerStatus.SIGNED_UP);
		if (!exists(lecturer.getEmail())) {			
			lecturerDAO.save(lecturer);
			LOG.info("New lecturer has been registered [" + lecturer.getFirstName() + " " + lecturer.getLastName() + "]");
		} else {
			throw new BusinessException(ErrorCodes.ERROR_EMAIL_EXISTS);
		}
	}
	
	@Override
	public Page<Lecturer> listLatestByStatus(int pageNumber, int itemsPerPage, LecturerStatus status) {
		return lecturerDAO.findByStatus(status, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage, "modified");
	}

	@Override
	public Page<Lecturer> listAll(int pageNumber, int itemsPerPage) {
		return lecturerDAO.findAll(Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage);
	}

	@Override
	public Page<Lecturer> listSignedUp(int pageNumber, int itemsPerPage) {
		return lecturerDAO.findByStatus(LecturerStatus.SIGNED_UP, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage, "rating");
	}

	@Override
	public Page<Lecturer> listActive(int pageNumber, int itemsPerPage) {
		return lecturerDAO.findByStatus(LecturerStatus.ACTIVE, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage, "rating");
	}

	@Override
	public Page<Lecturer> listRejected(int pageNumber, int itemsPerPage) {
		return lecturerDAO.findByStatus(LecturerStatus.REJECTED, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage, "rating");
	}

	@Override
	public Page<Lecturer> listRetired(int pageNumber, int itemsPerPage) {
		return lecturerDAO.findByStatus(LecturerStatus.RETIRED, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage, "rating");
	}

	@Override
	public void acceptRegistration(Lecturer lecturer) {
		LecturerPreconditions.acceptRegistration(lecturer);
		lecturer.setStatus(LecturerStatus.ACTIVE);
		lecturerDAO.save(lecturer);
		LOG.info("Registration accepted for lecturer [" + lecturer.getCode() + "]" );
	}

	@Override
	public void rejectRegistration(Lecturer lecturer) {
		LecturerPreconditions.rejectRegistration(lecturer);
		lecturer.setStatus(LecturerStatus.REJECTED);
		lecturerDAO.save(lecturer);		
		LOG.info("Registration rejected for lecturer [" + lecturer.getCode() + "]" );
	}

	@Override
	public void retireLecturer(Lecturer lecturer) {
		LecturerPreconditions.retireLecturer(lecturer);
		lecturer.setStatus(LecturerStatus.RETIRED);
		lecturerDAO.save(lecturer);				
		LOG.info("Lecturer retired [" + lecturer.getCode() + "]");
	}
	
	@Override
	public List<Course> fetchCoursesForLecturer(Lecturer lecturer) {
		return courseDAO.findByLecturer(lecturer.getId());
	}
	
	@Override
	public Lecturer load(Long id) {
		return lecturerDAO.find(Lecturer.class, id);
	}
	
	@Override
	public void saveChanges(Lecturer lecturer) {
		Assert.notNull(lecturer.getId(), PreconditionExceptions.ID_IS_NULL);
		lecturerDAO.save(lecturer);
		LOG.info("Lecturer modified [" + lecturer.getCode() + "]");
	}
	
	@Override
	public boolean exists(String email) {
		try {
			lecturerDAO.findAnyByEmail(email);
		} catch (NoResultException e) {
			return false;
		}
		return true;
	}
	
	@Override
	public Lecturer findByEmail(String email) {
		Lecturer lecturer = null;
		try {
			lecturer = lecturerDAO.findActiveByEmail(email);
		} catch (NoResultException e) {
			;
		}
		return lecturer;
	}
	
	@Override
	public List<Lecturer> fetchActive() {
		return lecturerDAO.findByStatus(LecturerStatus.ACTIVE, "rating");
	}

}